package kayao.server.threads;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Random;
import kayao.common.KayaoValues;
import kayao.common.NetworkUtils;
import kayao.server.AreaManager;
import kayao.server.DesktopServer;

public class ListeningThread extends Thread {

protected DatagramSocket requestsSocket=null;
protected InetAddress inetAddress;
protected String mServerIP = "";
protected String mClientIP = "";
//protected static long mTimeResendingNotYourKing=0;
//protected static Vector<Integer> mExpectingKingRequest=new Vector<Integer>();
//protected byte []mNotYourKingData=null;
	
	/**
	 *	It creates the Magic Number and the socket to listen.
	 *  Then, it launches the listening method. 
	 */
	public void run()
	{
		//Create the magic number
		Random generator = new Random(System.currentTimeMillis());
		KayaoValues.MAGIC_NUMBER=generator.nextInt(Integer.MAX_VALUE);

		//Start listening
		try
		{
			inetAddress = InetAddress.getLocalHost();
			mServerIP = inetAddress.getHostAddress();
			KayaoValues.SERVER_IP = mServerIP;
			requestsSocket= new DatagramSocket(KayaoValues.SERVER_PORT, inetAddress);
			//Read requests
			readRequests();
		}
		catch(Exception e)
		{
			//Basic treatment at the moment... show message and restart the reading
			System.out.println("Error in ListeningThread: The socket to listen couldn't be created: "+e.getMessage());
		}
		
	}

	/**
	 * It waits in an infinite loop getting blocked until a request comes.
	 * Then it adds a new thread to treat it and listen again.
	 * 
	 * If an error happen it shows it and listen again.
	 */
	private void readRequests() 
	{
		try
		{
			//Create packet to receive requests
			DatagramPacket packet=new DatagramPacket(new byte[100], 100);		
			
			//Show our IP in console to share later with hosts easily
			System.out.println("IP: "+mServerIP+"\n");
			
			while(true)
			{
				//Block thread reading
				requestsSocket.receive(packet);
				byte[] dataReceived = packet.getData();
				// Save the IP of the client
				mClientIP = packet.getAddress().toString().substring(1);
				
				if (DesktopServer.find(mClientIP) == null){
					if(dataReceived[0]==KayaoValues.PLAYING_REQUEST_MESSAGE)
					{
						//Create thread to treat it
						System.out.println(DesktopServer.getTimestamp()+" [Server] Login request from: " + mClientIP);
						DesktopServer.addLoginThread(mClientIP, dataReceived, requestsSocket);
					}
				}
				//First byte is the type of the message or the magic number
				else if(NetworkUtils.insertByteArrayToInt(dataReceived, 0)!=KayaoValues.MAGIC_NUMBER)
				{
					System.out.println(DesktopServer.getTimestamp()+" [Server] Bad request from: " + mClientIP + ". It failed the magicnumber");
				}
				else if(dataReceived[4]==KayaoValues.WHAT_TIME_IS_IT_MESSAGE){
					System.out.println(DesktopServer.getTimestamp()+" [Server] Time request from: " + mClientIP);					
					DesktopServer.addTimeThread(mClientIP, packet.getPort(), requestsSocket);
				}
				else if(dataReceived[4]==KayaoValues.LOGOUT_MSG){
					System.out.println(DesktopServer.getTimestamp()+" [Server] LogOut request from: " + mClientIP);					
					DesktopServer.removeClient(DesktopServer.find(mClientIP));
				}
				else if(dataReceived[4]==KayaoValues.KING_REQUEST_MESSAGE)
				{
					//Create thread to treat it
					System.out.println(DesktopServer.getTimestamp()+" [Server] Kings request from: " + mClientIP);
					DesktopServer.addKingsRequestThread(mClientIP, KayaoValues.CLIENT_READ_PORT, dataReceived, requestsSocket);
				}
				else if(dataReceived[4]==KayaoValues.DEAD_CLIENT)
				{
					//When we get this, we disable the client bing a king
					System.out.println(DesktopServer.getTimestamp()+" [Server] DeadClient notify from: " + mClientIP);
					System.out.println("[Server] Dead client ID: " + NetworkUtils.insertByteArrayToInt(dataReceived, 5)+"\n");
					AreaManager.deleteKingById(NetworkUtils.insertByteArrayToInt(dataReceived, 5));
				}
				/*Resend messages for king requests??
				if(!(mTimeResendingNotYourKing==0))
				{
					//Send to everybody again
					;
					mTimeResendingNotYourKing=System.currentTimeMillis();
				}*/
					
			}
		}
		catch(Exception e)
		{
			//Basic treatment at the moment... show message and restart the reading
			System.out.println("Error in listening thread: Error receiving packet: "+e.getMessage());
			//Some exceptions...
			
			//Come back to read
			readRequests();
		}
	}
/*
	public static void addExpectingKingRequest(Vector<Integer> news) {
		for(int i=0;i<news.size();i++)
			mExpectingKingRequest.add(news.get(i));
		mTimeResendingNotYourKing=System.currentTimeMillis();
		
	}
	*/

	public DatagramSocket getSocket() {
		
		return requestsSocket;
	}
}
